package vistop.io.lisp;

import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.logging.Logger;

import org.armedbear.lisp.LispObject;
import org.armedbear.lisp.Nil;

public class MyLispObject {
	
	Logger logg = Logger.getLogger(this.getClass().getPackage().getName());
	
	private LispType name;
	private Map<AttributeName, Double> attributes;
	
	public MyLispObject(LispType name, LispObject lo) {
		this.name = name;
		this.attributes = new TreeMap<AttributeName, Double>();
		readAttributes(lo);
		
		logg.fine("New MyLispObject of type " + name + " with " +
				attributes.size() + " attributes is successfully created.");
	}
	
	public MyLispObject(LispObject lo) {
		this.attributes = new TreeMap<AttributeName, Double>();
		String name = readAttributes(lo);
		setName(name);
		
		logg.fine("New MyLispObject of type " + name + " with " +
				attributes.size() + " attributes is successfully created.");
	}
	
	private String readAttributes(LispObject lo) {
		String name = lo.car().princToString();
		int line = 1;
		
		for (LispObject props = lo.cdr() ; props != Nil.NIL; props = props.cddr()) {
			String k = props.car().princToString();
			if (getAttributeName(k) == null) {
				logg.warning(k + " is undefined Attribute Type. This " +
						"attribute will be discarded.");
			} else {
				AttributeName key = getAttributeName(k);
				String v = props.cadr().princToString();
				try {
					double value = Double.parseDouble(v);

					attributes.put(key, value);
				} catch(Exception e) {
					e.printStackTrace();
					System.out.println("line nr: " + line + " key = " + key +
							" value = " + v);
				}
				
			}
			line++;
		}
		return name;
	}
	
	private static AttributeName getAttributeName (String name) {
		try{
			return Enum.valueOf(AttributeName.class, name);
		}catch(IllegalArgumentException e){
			return null;
		}
	}

	private void setName(String name) {
		try {
			this.name = Enum.valueOf(LispType.class, name);
		} catch (IllegalArgumentException e){
			logg.warning(name + " is an undefined Lisp Type. Name will be" +
				" set to UNKNOWN.");	
			this.name = LispType.UNKNOWN;
		}
	}
	
	public double getAttribute(AttributeName key) {
		return attributes.get(key);
	}
	
	
	public LispType getName() {
		return this.name;
	}
	
	public Map<AttributeName, Double> getAttributes() {
		return this.attributes;
	}
	
	public Map<AttributeName, Double> removeAttribute(AttributeName name) {
		this.attributes.remove(name);
		return this.attributes;
	}
	
	public String toString() {
		String str = "LispObject: ";
		str += name.toString() + " { ";
		for (Entry<AttributeName, Double> a : attributes.entrySet()) {
			str += a.getKey().name() + " = " + a.getValue() + " ";
		}
		return str + "}\n";
	}
}
